package pCloud.acesscontrol;

/*
 * @(#)SimplePDP.java
 *
 * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *   1. Redistribution of source code must retain the above copyright notice,
 *      this list of conditions and the following disclaimer.
 * 
 *   2. Redistribution in binary form must reproduce the above copyright
 *      notice, this list of conditions and the following disclaimer in the
 *      documentation and/or other materials provided with the distribution.
 *
 * Neither the name of Sun Microsystems, Inc. or the names of contributors may
 * be used to endorse or promote products derived from this software without
 * specific prior written permission.
 * 
 * This software is provided "AS IS," without a warranty of any kind. ALL
 * EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
 * ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
 * OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MICROSYSTEMS, INC. ("SUN")
 * AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
 * AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
 * DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
 * REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
 * INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
 * OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
 * EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
 *
 * You acknowledge that this software is not designed or intended for use in
 * the design, construction, operation or maintenance of any nuclear facility.
 */

import com.sun.xacml.AbstractPolicy;
import com.sun.xacml.ConfigurationStore;
import com.sun.xacml.Indenter;
import com.sun.xacml.ParsingException;
import com.sun.xacml.PDP;
import com.sun.xacml.PDPConfig;

import com.sun.xacml.attr.IntegerAttribute;
import com.sun.xacml.cond.FunctionFactory;
import com.sun.xacml.cond.FunctionFactoryProxy;
import com.sun.xacml.cond.StandardFunctionFactory;

import com.sun.xacml.ctx.Attribute;
import com.sun.xacml.ctx.RequestCtx;
import com.sun.xacml.ctx.ResponseCtx;

import com.sun.xacml.finder.AttributeFinder;
import com.sun.xacml.finder.PolicyFinder;

import com.sun.xacml.finder.impl.CurrentEnvModule;
import com.sun.xacml.finder.impl.FilePolicyModule;
import com.sun.xacml.finder.impl.SelectorModule;

import java.io.FileInputStream;
import java.io.IOException;

import java.net.URI;
import java.net.URISyntaxException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import java.util.Iterator;

import pCloud.TimeInRangeFunction;
import pCloud.message.PolicyQueryReply;

/**
 * A simple PDP, using FilePolicyModule as the PolicyFinderModule
 */
public class PCloudPDP {

	// this is the actual PDP object we'll use for evaluation
	private PDP pdp = null;

	private RequestCtx requestContext;

	FilePolicyModule filePolicyModule;

	PolicyFinder policyFinder;

	public RequestCtx getRequestContext() {
		return requestContext;
	}

	public void init() {
		this.filePolicyModule = new FilePolicyModule();

		// next, setup the PolicyFinder that this PDP will use
		this.policyFinder = new PolicyFinder();
		Set policyModules = new HashSet();
		policyModules.add(filePolicyModule);
		policyFinder.setModules(policyModules);

		// now setup attribute finder modules for the current date/time and
		// AttributeSelectors (selectors are optional, but this project does
		// support a basic implementation)
		CurrentEnvModule envAttributeModule = new CurrentEnvModule();
		SelectorModule selectorAttributeModule = new SelectorModule();

		// Setup the AttributeFinder just like we setup the PolicyFinder. Note
		// that unlike with the policy finder, the order matters here. See the
		// the javadocs for more details.
		AttributeFinder attributeFinder = new AttributeFinder();
		List attributeModules = new ArrayList();
		attributeModules.add(envAttributeModule);
		attributeModules.add(selectorAttributeModule);
		attributeFinder.setModules(attributeModules);

		// Try to load the time-in-range function, which is used by several
		// of the examples...see the documentation for this function to
		// understand why it's provided here instead of in the standard
		// code base.
		FunctionFactoryProxy proxy = StandardFunctionFactory
				.getNewFactoryProxy();
		FunctionFactory factory = proxy.getConditionFactory();
		factory.addFunction(new TimeInRangeFunction());
		FunctionFactory.setDefaultFactory(proxy);

		// finally, initialize our pdp
		pdp = new PDP(new PDPConfig(attributeFinder, policyFinder, null));
	}

	public boolean loadPolicy(String fileName) {
		return this.filePolicyModule.addPolicy(fileName, this.policyFinder);
	}

	public boolean removePolicy(String fileName) {
		return this.filePolicyModule.removePolicy(fileName);
	}

	public Object queryPolicy() {
		HashMap<String, AbstractPolicy> activePolicies = this.filePolicyModule
				.getPolicies();
		PolicyQueryReply pqr = new PolicyQueryReply();
		Iterator<String> it = activePolicies.keySet().iterator();

		String key;
		int index;
		String id;
		while (it.hasNext()) {
			key = it.next();
			index = new Integer(key.split("_")[2]).intValue();
			id = activePolicies.get(key).getId().toString();
			pqr.addPolicyInfo(index, id);
		}
		return pqr;
	}

	public void setRequestCtx(String requestFile) throws IOException,
			ParsingException {
		requestContext = RequestCtx
				.getInstance(new FileInputStream(requestFile));
	}

	/**
	 * Evaluates the given request and returns the Response that the PDP will
	 * hand back to the PEP.
	 * 
	 * @param requestFile
	 *            the name of a file that contains a Request
	 * 
	 * @return the result of the evaluation
	 * 
	 * @throws IOException
	 *             if there is a problem accessing the file
	 * @throws ParsingException
	 *             if the Request is invalid
	 */
	public ResponseCtx evaluate() throws IOException, ParsingException {
		// evaluate the request
		return pdp.evaluate(requestContext);
	}

}
